package co.yixiang.vod.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.UploadFileRequest;
import com.aliyun.oss.model.UploadFileResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.*;
import co.yixiang.vod.config.VodProperties;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 阿里云视频点播服务操作
 */
@Slf4j
@RequiredArgsConstructor
public class VodTemplate implements InitializingBean {

    private final VodProperties vodProperties;
    private DefaultAcsClient client;

    public DefaultAcsClient initVodClient () {
        DefaultProfile profile = DefaultProfile.getProfile(vodProperties.getRegion(), vodProperties.getAccessKey(), vodProperties.getSecretKey());
        return new DefaultAcsClient(profile);
    }

    /**
     * 获取视频上传地址和凭证
     *
     * @param title       视频标题
     * @param fileName    文件名
     * @param description 视频描述
     * @return 上传地址和凭证
     */
    @SneakyThrows
    public CreateUploadVideoResponse createUploadVideo(String title, String fileName, String description) {
        CreateUploadVideoRequest request = new CreateUploadVideoRequest();
        request.setTitle(title);
        request.setFileName(fileName);
        if (StrUtil.isNotBlank(description)) {
            request.setDescription(description);
        }
        if (StrUtil.isNotBlank(vodProperties.getTemplateGroupId())) {
            request.setTemplateGroupId(vodProperties.getTemplateGroupId());
        }
        if (StrUtil.isNotBlank(vodProperties.getWorkflowId())) {
            request.setWorkflowId(vodProperties.getWorkflowId());
        }
        if (StrUtil.isNotBlank(vodProperties.getStorageLocation())) {
            request.setStorageLocation(vodProperties.getStorageLocation());
        }
        if (StrUtil.isNotBlank(vodProperties.getCategoryId())) {
            request.setCateId(Long.parseLong(vodProperties.getCategoryId()));
        }

        return client.getAcsResponse(request);
    }

    /**
     * 刷新视频上传凭证
     *
     * @param videoId 视频ID
     * @return 上传凭证
     */
    @SneakyThrows
    public RefreshUploadVideoResponse refreshUploadVideo(String videoId) {
        RefreshUploadVideoRequest request = new RefreshUploadVideoRequest();
        request.setVideoId(videoId);
        return client.getAcsResponse(request);
    }

    /**
     * 获取视频播放地址
     *
     * @param videoId 视频ID
     * @return 播放地址
     */
    @SneakyThrows
    public String getPlayInfo(String videoId) {
        GetPlayInfoRequest request = new GetPlayInfoRequest();
        request.setVideoId(videoId);

        GetPlayInfoResponse response = client.getAcsResponse(request);

        List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();

        String url = "";
        if (playInfoList.size() == 1) {
            url = playInfoList.get(0).getPlayURL();//会返回两个url，第一个是m3u8格式的，我们用第二个就好
        } else if (playInfoList.size() == 2) {
            url = playInfoList.get(1).getPlayURL();//会返回两个url，第一个是m3u8格式的，我们用第二个就好
        }

        /*List<Map<String, String>> playInfoList = new ArrayList<>();
        for (GetPlayInfoResponse.PlayInfo playInfo : response.getPlayInfoList()) {
            Map<String, String> playInfoMap = new HashMap<>();
            playInfoMap.put("url", playInfo.getPlayURL());
            playInfoMap.put("definition", playInfo.getDefinition());
            playInfoMap.put("format", playInfo.getFormat());
            playInfoMap.put("duration", String.valueOf(playInfo.getDuration()));
            playInfoMap.put("size", String.valueOf(playInfo.getSize()));
            playInfoList.add(playInfoMap);
        }*/
        return url;
    }

    /**
     * 获取视频播放凭证
     *
     * @param videoId 视频ID
     * @return 播放凭证
     */
    @SneakyThrows
    public String getPlayAuth(String videoId) {
        GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
        request.setVideoId(videoId);
        GetVideoPlayAuthResponse response = client.getAcsResponse(request);
        return response.getPlayAuth();
    }

    /**
     * 获取视频信息
     *
     * @param videoId 视频ID
     * @return 视频信息
     */
    @SneakyThrows
    public Map<String, Object> getVideoInfo(String videoId) {
        GetVideoInfoRequest request = new GetVideoInfoRequest();
        request.setVideoId(videoId);
        GetVideoInfoResponse response = client.getAcsResponse(request);

        Map<String, Object> videoInfo = new HashMap<>();
        videoInfo.put("videoId", response.getVideo().getVideoId());
        videoInfo.put("title", response.getVideo().getTitle());
        videoInfo.put("description", response.getVideo().getDescription());
        videoInfo.put("duration", response.getVideo().getDuration());
        videoInfo.put("coverUrl", response.getVideo().getCoverURL());
        videoInfo.put("status", response.getVideo().getStatus());
        videoInfo.put("creationTime", response.getVideo().getCreationTime());
        videoInfo.put("size", response.getVideo().getSize());
        return videoInfo;
    }

    /**
     * 删除视频
     *
     * @param videoId 视频ID
     */
    @SneakyThrows
    public void deleteVideo(String videoId) {
        DeleteVideoRequest request = new DeleteVideoRequest();
        request.setVideoIds(videoId);
        client.getAcsResponse(request);
    }

    /**
     * 批量删除视频
     *
     * @param videoIds 视频ID列表，最多支持20个
     */
    @SneakyThrows
    public void deleteVideos(List<String> videoIds) {
        if (videoIds == null || videoIds.isEmpty() || videoIds.size() > 20) {
            throw new IllegalArgumentException("视频ID列表不能为空且最多支持20个");
        }
        DeleteVideoRequest request = new DeleteVideoRequest();
        request.setVideoIds(String.join(",", videoIds));
        client.getAcsResponse(request);
    }

    /**
     * 上传视频文件（本地文件方式）
     *
     * @param title       视频标题
     * @param description 视频描述
     * @param fileName    文件名
     * @param filePath    本地文件路径
     * @return 视频ID
     */
    @SneakyThrows
    public String uploadVideo(String title, String description, String fileName, String filePath) {
        // 获取上传凭证
        CreateUploadVideoResponse response = createUploadVideo(title, fileName, description);
        String videoId = response.getVideoId();

        // 使用OSS上传文件
        OSS ossClient = new OSSClientBuilder().build(
                "oss-" + vodProperties.getRegion() + ".aliyuncs.com",
                vodProperties.getAccessKey(),
                vodProperties.getSecretKey());

        try {
            UploadFileRequest uploadFileRequest = new UploadFileRequest(vodProperties.getStorageLocation(), fileName);
            uploadFileRequest.setUploadFile(filePath);
            UploadFileResult uploadResult = ossClient.uploadFile(uploadFileRequest);
            log.info("视频上传成功，videoId: {}", videoId);
            return videoId;
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 上传视频文件（MultipartFile方式）
     *
     * @param title       视频标题
     * @param description 视频描述
     * @param file        MultipartFile文件
     * @return 视频ID
     */
    @SneakyThrows
    public String uploadVideo(String title, String description, MultipartFile file) {
        // 检查文件大小
        long fileSize = file.getSize() / 1024 / 1024; // 转换为MB
        if (fileSize > vodProperties.getMaxSize()) {
            throw new IllegalArgumentException("文件大小超过限制，最大允许" + vodProperties.getMaxSize() + "MB");
        }

        // 获取文件名和后缀
        String originalFilename = file.getOriginalFilename();
        String fileName = IdUtil.simpleUUID() + "." + StrUtil.subAfter(originalFilename, ".", true);

        // 创建临时文件
        File tempFile = File.createTempFile("vod_", "." + StrUtil.subAfter(originalFilename, ".", true));
        file.transferTo(tempFile);

        try {
            // 上传视频
            return uploadVideo(title, description, fileName, tempFile.getAbsolutePath());
        } finally {
            // 删除临时文件
            if (tempFile.exists()) {
                tempFile.delete();
            }
        }
    }

    /**
     * 获取视频分类列表
     *
     * @return 分类列表
     */
    @SneakyThrows
    public List<Map<String, Object>> getCategoryList() {
        GetCategoriesRequest request = new GetCategoriesRequest();
        GetCategoriesResponse response = client.getAcsResponse(request);

        List<Map<String, Object>> categoryList = new ArrayList<>();
        for (GetCategoriesResponse.Category category : response.getSubCategories()) {
            Map<String, Object> categoryMap = new HashMap<>();
            categoryMap.put("categoryId", category.getCateId());
            categoryMap.put("categoryName", category.getCateName());
            categoryMap.put("level", category.getLevel());
            categoryList.add(categoryMap);
        }
        return categoryList;
    }

    /**
     * 获取视频列表
     *
     * @param status    视频状态：全部(默认)，上传中，上传成功，上传失败，转码中，转码成功，转码失败
     * @param pageNo    页码，默认1
     * @param pageSize  每页记录数，默认10，最大不超过100
     * @return 视频列表
     */
    @SneakyThrows
    public Map<String, Object> getVideoList(String status, Integer pageNo, Integer pageSize) {
        SearchMediaRequest request = new SearchMediaRequest();
        request.setPageNo(pageNo);
        request.setPageSize(pageSize);
        if (StrUtil.isNotBlank(status)) {
            request.setFields("Status");
            request.setMatch("Status=" + status);
        }
        SearchMediaResponse response = client.getAcsResponse(request);

        Map<String, Object> result = new HashMap<>();
        result.put("total", response.getTotal());
//        result.put("pageNo", response.getPageNo());
//        result.put("pageSize", response.getPageSize());

        List<Map<String, Object>> videoList = new ArrayList<>();
        for (SearchMediaResponse.Media media : response.getMediaList()) {
            Map<String, Object> videoMap = new HashMap<>();
            videoMap.put("videoId", media.getVideo().getVideoId());
            videoMap.put("title", media.getVideo().getTitle());
            videoMap.put("description", media.getVideo().getDescription());
            videoMap.put("coverUrl", media.getVideo().getCoverURL());
            videoMap.put("status", media.getVideo().getStatus());
            videoMap.put("creationTime", media.getVideo().getCreationTime());
            videoMap.put("duration", media.getVideo().getDuration());
            videoMap.put("size", media.getVideo().getSize());
            videoList.add(videoMap);
        }
        result.put("videoList", videoList);
        return result;
    }

    /**
     * Spring Bean初始化时的回调方法，用于创建阿里云视频点播服务的客户端实例。
     * 该方法实现自{@link InitializingBean}接口，在Spring容器完成Bean属性注入后自动调用。
     * 通过配置的区域、访问密钥和安全密钥创建阿里云VOD客户端，用于后续的视频点播服务操作。
     */
    @Override
    public void afterPropertiesSet() {
        DefaultProfile profile = DefaultProfile.getProfile(
                vodProperties.getRegion(),
                vodProperties.getAccessKey(),
                vodProperties.getSecretKey());
        this.client = new DefaultAcsClient(profile);
    }
}